EC2インスタンスにIAMロールを自動アタッチする仕組みをテンプレート化してみた
EC2インスタンスに「特定IAMロール」を必ず割り当てる仕組みを作ってみました。
作ったもの(構成図)
構成要素は以下のとおりです。
EC2ロール(インスタンスプロファイル)
自動アタッチさせたい EC2ロール(インスタンスプロファイル)です。
後述するテンプレートには以下権限を割り当てています。 SSMを活用する上である程度必要になってくる権限を付与しました。
- CloudWatchAgentServerPolicy(AWS管理ポリシー)
- AmazonSSMManagedInstanceCore(AWS管理ポリシー)
- AmazonSSMPatchAssociation(AWS管理ポリシー)
Session Managerログ保管用バケット
への PutObject/PutObjectAcl 権限
SSM State Manager 関連付け
Systems Manager(SSM) State Manager はインスタンスのあるべき状態を定義するものです。 この定義は 関連付け(Association) と言います。 関連付けには以下のような設定パラメータがあります。
- 対象: どのインスタンスの状態を定義するか
- 実行ドキュメント: どのドキュメントを実行するか
- スケジュール: どの頻度で実行するか(or 1回のみの実施か)
今回は以下のような関連付け(および実行のためのSSMロール)を作りました。
- 対象: すべてのインスタンス
- 実行ドキュメント: AWS-AttachIAMToInstance
- スケジュール: 1時間ごと
作ったもの(コード)
テンプレートがこちら。
AWSTemplateFormatVersion: '2010-09-09' Parameters: # ##### # Parameters for EC2 Role, Instance Profile # ##### EC2RoleName: Type: String Default: "EC2DefaultRole" SSMSessionManagerLogBucketName: Type: String Default: "DOC-EXAMPLE-BUCKET" # ##### # Parameters for SSM Role # ##### SSMRoleName: Type: String Default: "SSMAutomationRole-AMIAttachToEC2" # ##### # Parameters for SSM Association # ##### AssociationName: Type: String Default: "auto-ec2-role-attach" ForceReplace: Type: String Default: "true" AllowedValues: - "true" - "false" Resources: # ##### # EC2 Role, Instance Profile # ##### EC2Role: Type: AWS::IAM::Role Properties: RoleName: !Ref EC2RoleName Description: "This role must be attached all EC2 instances." AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: "ec2.amazonaws.com" Action: "sts:AssumeRole" ManagedPolicyArns: - "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy" - "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" - "arn:aws:iam::aws:policy/AmazonSSMPatchAssociation" Policies: - PolicyName: S3Logging PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: - "s3:PutObject" - "s3:PutObjectAcl" Resource: !Sub "arn:aws:s3:::${SSMSessionManagerLogBucketName}/*" EC2InstanceProfile: Type: AWS::IAM::InstanceProfile Properties: InstanceProfileName: !Ref EC2Role Roles: - !Ref EC2Role # ##### # SSM Role for automation # ##### SSMRole: Type: AWS::IAM::Role Properties: RoleName: !Ref SSMRoleName Description: "role for SSM automation: EC2 role attach" AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: "ssm.amazonaws.com" Action: "sts:AssumeRole" Policies: - PolicyName: AWS-AttachIAMToInstance PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: - "ec2:DescribeIamInstanceProfileAssociations" - "ec2:DisassociateIamInstanceProfile" - "ec2:AssociateIamInstanceProfile" - "iam:ListInstanceProfilesForRole" - "iam:GetInstanceProfile" Resource: "*" - Effect: "Allow" Action: "iam:PassRole" Resource: !GetAtt EC2Role.Arn # ##### # SSM Association # ##### SSMAssociation: Type: AWS::SSM::Association Properties: AssociationName: !Ref AssociationName Name: AWS-AttachIAMToInstance ApplyOnlyAtCronInterval: true ScheduleExpression: "cron(0 0/1 * * ? *)" Targets: - Key: InstanceIds Values: - "*" # Targets: # - Key: "tag:CCoEManaged" # Values: # - "true" AutomationTargetParameterName: InstanceId Parameters: AutomationAssumeRole: - !GetAtt SSMRole.Arn ForceReplace: - !Ref ForceReplace RoleName: - !Ref EC2Role
パラメータには以下を指定します。
パラメータ名 | 説明 |
---|---|
EC2RoleName | EC2ロールの名前 |
SSMSessionManagerLogBucketName | Session Manager のログ格納用バケットの名前 |
SSMRoleName | SSMロールの名前 |
AssociationName | SSM State Manager 関連付けの名前 |
ForceReplace | 既存のEC2ロールを強制的に置換するか |
試してみる
CFnテンプレートの展開
パラメータを入力してスタックを作成します。 (SSM Session Manager ログ用バケットは事前に準備必要です)
以下リソースが作られました。
EC2インスタンスを作成してみた
ロールを付与せずにEC2インスタンスを1つ作成しました。
時間を置いて見てみると、以下のようにロールが付与されていました。
次に「他のロール」をアタッチしてみました。
しばらくすると、以下のようにロールが付け替えられていました。
(もしロールの付替えを防ぎたい場合は CFnパラメータの ForceReplace
を変えることで実現できるはずです。)
(参考) SSMのログ
SSM State Manager の関連付けからは実行履歴を見られます。
内部で実行している AWS-AttachIAMToInstance
Automation のログは以下のようになります。
おわりに
「EC2インスタンスにIAMロールを自動アタッチする」仕組みを作ってみました。
ちなみに、EC2ロールの自動アタッチ自体は SSM高速セットアップで可能です。 そこでアタッチされるEC2ロールの権限が不足していて、カスタマイズしたい要件 がある場合に、この方法を試してみると良いと思います。
また、もし対象インスタンスを絞りたい場合は、 SSMAssociation の以下コメントしている部分に置き換えます。タグのキー/値に相当するインスタンスが対象になります。
Targets: - Key: InstanceIds Values: - "*" # Targets: # - Key: "tag:CCoEManaged" # Values: # - "true"